/* 
 * File:   Xcom.cpp
 * Author: minaev
 * 
 * Created on 11 Октябрь 2013 г., 13:46
 */

#include "Xcom.h"
#include "Xmsg.h"
#include "Xservice.h"
#include <termios.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <stdio.h>

/**
 * Create COM connection
 * @param filetty - /dev/tty*
 * @param baudrate - B9600, B38400, B115200, ...(termios.h)
 */
Xcom::Xcom(const char* filetty, speed_t baudrate) {
    fileDsc = open(filetty, O_RDWR | O_NOCTTY /*| O_NDELAY*/);
    if (fileDsc == -1) {
        Xmsg::log(3,"FATAL ERROR: Device ",filetty," unable");
        exit(1);
    }
    //fast read (without wait)
    fcntl(fileDsc, F_SETFL, FNDELAY);
    //slow read (with wait)
    //fcntl(fileDsc, F_SETFL, 0);
    
    
    tcgetattr(fileDsc, &comSettings);
    
    comSettings.c_cflag |= (CLOCAL | CREAD);
    cfsetspeed(&comSettings, baudrate);//baudrate

    
    comSettings.c_cflag &= ~CSIZE;//Size 8 bit
    comSettings.c_cflag |= CS8;
    comSettings.c_cflag &= ~PARENB; //No parity
    comSettings.c_cflag &= ~CSTOPB; //1 stop bit
    
    comSettings.c_cflag &= ~CRTSCTS; //No hard control flow 
    comSettings.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); //Raw data flow
    
    comSettings.c_iflag &= ~(IXON | IXOFF | IXANY); //no soft control input flow
    comSettings.c_oflag &= ~OPOST;//no soft control output flow
    
    tcsetattr(fileDsc, TCSANOW, &comSettings);
}

Xcom::Xcom(const Xcom& orig) {
}

Xcom::~Xcom() {
    close(fileDsc);
}

/**
 * Write to COM port
 * @param sendBuf - sending buffer
 * @param size - count bytes for sending
 */
void Xcom::xwrite(const char* sendBuf, int size){
    //Xmsg::printf("send:\n");
    //Xservice::printArrayToHexStr(sendBuf,size);
    write(fileDsc,sendBuf,size);
}

/**
 * Read in COM port
 * @param receiveBuf - receive buffer
 * @param size - count bytes for receive
 * @return count received bytes. If available bytes in receive buffer less size
 * then return -1;
 */
int Xcom::xread(char* receiveBuf, int size){
    if(size>availBytes()){
        return -1;
    }
    return read(fileDsc,receiveBuf,size);
}

/**
 * 
 * @return Count bytes in input buffer.
 */
int Xcom::availBytes(){
    static int res;
    ioctl(fileDsc, FIONREAD, &res);
    return res;
}